package com.xiaoyung.easyisapisdk.common.util.bean;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.ConvertUtils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xiaoyung.easyisapisdk.common.util.StringUtils;

/**
 * Bean 工具类
 * 
 * 
 */
public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {
	/** Bean方法名中属性名开始的下标 */
	private static final int BEAN_METHOD_PROP_INDEX = 3;

	/** * 匹配getter方法的正则表达式 */
	private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");

	/** * 匹配setter方法的正则表达式 */
	private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");

	static {
		//创建日期转换器对象
		//解决 org.apache.commons.beanutils.BeanUtils.populate(bean, newMap); Date为null会报错
		//ConvertUtils.register(new DateConverter(null), Date.class);
		ConvertUtils.register(new MyDateConverter(), Date.class);
		ConvertUtils.register(new JSONConvert(), JSON.class);
		ConvertUtils.register(new JSONConvert(), JSONObject.class);
		ConvertUtils.register(new JSONConvert(), JSONArray.class);
	}
	/**
	 * Bean属性复制工具方法。
	 * 
	 * @param dest 目标对象
	 * @param src  源对象
	 */
	public static void copyBeanProp(Object dest, Object src) {
		try {
			copyProperties(src, dest);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取对象的setter方法。
	 * 
	 * @param obj 对象
	 * @return 对象的setter方法列表
	 */
	public static List<Method> getSetterMethods(Object obj) {
		// setter方法列表
		List<Method> setterMethods = new ArrayList<Method>();

		// 获取所有方法
		Method[] methods = obj.getClass().getMethods();

		// 查找setter方法

		for (Method method : methods) {
			Matcher m = SET_PATTERN.matcher(method.getName());
			if (m.matches() && (method.getParameterTypes().length == 1)) {
				setterMethods.add(method);
			}
		}
		// 返回setter方法列表
		return setterMethods;
	}

	/**
	 * 获取对象的getter方法。
	 * 
	 * @param obj 对象
	 * @return 对象的getter方法列表
	 */

	public static List<Method> getGetterMethods(Object obj) {
		// getter方法列表
		List<Method> getterMethods = new ArrayList<Method>();
		// 获取所有方法
		Method[] methods = obj.getClass().getMethods();
		// 查找getter方法
		for (Method method : methods) {
			Matcher m = GET_PATTERN.matcher(method.getName());
			if (m.matches() && (method.getParameterTypes().length == 0)) {
				getterMethods.add(method);
			}
		}
		// 返回getter方法列表
		return getterMethods;
	}

	/**
	 * 检查Bean方法名中的属性名是否相等。<br>
	 * 如getName()和setName()属性名一样，getName()和setAge()属性名不一样。
	 * 
	 * @param m1 方法名1
	 * @param m2 方法名2
	 * @return 属性名一样返回true，否则返回false
	 */

	public static boolean isMethodPropEquals(String m1, String m2) {
		return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
	}
	
	

	public static <T> T fillBeanUseSourceIgnoreNull(T dest,T source) {
		fillBeanUseMap(dest, (JSONObject)(JSON.toJSON(source)));
		return dest;
	}
	
	public static <T> T fillBeanUseMap(T bean,Map<String,Object> map) {
		try {
			//忽略空值属性
			Set<String> emptyKeys = new HashSet<>();
			for(Entry<String, Object> entry : map.entrySet()) {
				String key = entry.getKey();
				Object value = entry.getValue();
				if(value==null ||  (value instanceof String && ((String)value).length()==0) ) {
					emptyKeys.add(key);
				}
			}
			emptyKeys.stream().forEach(k -> map.remove(k));
			
			//将field_prop这个map的属性 填充到this
			org.apache.commons.beanutils.BeanUtils.populate( bean, map);
		} catch (IllegalAccessException | InvocationTargetException e) {
			throw new RuntimeException(e);
		} 
		return bean;
	}
	
	
	
	public static <T> T mapToBean(Map<String,Object> map,T bean) {
		if(map==null) {
			return null;
		}
		//将field_prop这个map的属性 填充到this
				//XxxBean bean = new XxxBean();
		//Object bean = clazz.getDeclaredConstructor().newInstance();
		try {
			/*if(bean instanceof BaseEntity) {
				((BaseEntity)bean).buildFromPd(new PageData(map));
			}*/
			
			//value null 会报空指针 奇葩
			//Map<String,Object> newMap = map.entrySet().stream().collect(Collectors.toMap(entry -> StringUtils.toCamelCase(entry.getKey()), entry -> entry.getValue()));
			
			Map<String,Object> newMap = new HashMap<>();
			for (Map.Entry<String,Object> entry: map.entrySet()) {
				boolean toCamelCase = true;
				String key = StringUtils.underLineCamelConvert(entry.getKey(),toCamelCase );
				Object value = entry.getValue();
				/*if(key.equals("_createBy")||key.equals("_updateBy")) {
					if(value instanceof JSON) {
						value = JSON.toJavaObject((JSON)value, BaseUserInfoVo.class);
					}
				}*/
				newMap.put(key, value);
			}
			
			org.apache.commons.beanutils.BeanUtils.populate(bean, newMap);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return bean;
	}
	
	public static <T> T mapToBean(Map<String,Object> map,Class<T> clazz) {
		T bean = null;
		try {
			
			bean = clazz.getConstructor().newInstance();
			
			return mapToBean(map,bean);
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 
	}
}
